﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using GA_Scheduler;


namespace Acceron.Univerisy.Modules.Scheduling
{
    public class Item
    {
        public string Name { get; set; }
        public string Prof { get; set; }
    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : UserControl
    {
        System.Threading.Thread th;
        List<RoomControl> rooms = new List<RoomControl>();
        List<DayScheduleControl> dayList = new List<DayScheduleControl>();

        public MainWindow()
        {
            InitializeComponent();
            stopBut.IsEnabled = false;
            startBut.IsEnabled = false;
        }



        void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (th != null)
            {
                th.Abort();
            }
        }

        private void openBut_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.stackPanel1.Children.Clear();

                for (int i = 1; i < 8; i++)
                {
                    DayScheduleControl dcntrl = new DayScheduleControl()
                    {
                        DayOfTheWeek = i,
                        Groups = Configuration.Instance.Groups.ToList(),
                        Margin = new Thickness(10, 40, 0, 0),
                        Height = 900
                    };
                    dayList.Add(dcntrl);
                    stackPanel1.Children.Add(dcntrl);
                }

                stopBut.IsEnabled = false;
                openBut.IsEnabled = false;
                startBut.IsEnabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        AlgorithmDB algdb;

        private void startBut_Click(object sender, RoutedEventArgs e)
        {
            startBut.IsEnabled = false;

            algdb = new AlgorithmDB();
            algdb.NewBestSchedule += new EventHandler<AlgorithmDBEventArgs>(algdb_NewBestSchedule);
            algdb.StateChanged += new EventHandler<AlgorithmDBStateEventArgs>(algdb_StateChanged);
            th = new System.Threading.Thread(algdb.Start);
            th.Start();
            stopBut.IsEnabled = true;
        }

        void algdb_StateChanged(object sender, AlgorithmDBStateEventArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
            {
                switch (e.State)
                {
                    case AlgorithmState.AS_CRITERIA_STOPPED:
                        startBut.IsEnabled = true;
                        openBut.IsEnabled = true;
                        stopBut.IsEnabled = false;
                        break;
                    case AlgorithmState.AS_USER_STOPED:
                        startBut.IsEnabled = true;
                        openBut.IsEnabled = true;
                        stopBut.IsEnabled = false;
                        break;
                }
            }));
        }

        void algdb_NewBestSchedule(object sender, AlgorithmDBEventArgs e)
        {
            lock (this)
            {
                int nr = Configuration.Instance.NumberOfRooms;

                var slots = e.BestSchedule;

                int i = 0;

                foreach (var d in dayList)
                {
                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        label1.Content = "Population: " + e.Population;
                        label2.Content = "Fitness: " + e.BestSchedule.Fitness;

                        d.Clear();
                    }));
                }
                
                foreach (var sl in slots.Genes)
                {


                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        dayList[sl.DayOfWeek].AddNewCourse(sl);
                        //var groups = sl.Class.GroupClasses;
                        //foreach (var gr in groups)
                        //{
                        //    dayList[sl.DayOfWeek].AddNewCourse(sl.Pair, gr.Groupd_ID, sl.Class.Course.Name + "\n\n" + sl.Class.Professor.Name + "\n" + sl.Room.Name);
                        //}
                            
                    }));

                    
                    i++;
                
                }
                
            }
        }

        private void stopBut_Click(object sender, RoutedEventArgs e)
        {
            algdb.Stop();
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            
        }

        private void stopBut_Click_1(object sender, RoutedEventArgs e)
        {
            algdb.Stop();
        }

        private void savdbBtn_Click(object sender, RoutedEventArgs e)
        {
            if (algdb == null || algdb.BestChromosome == null)
                return;

            Configuration.Instance.Context.DaySchedules.DeleteAllOnSubmit(Configuration.Instance.Context.DaySchedules);

            foreach (var gen in algdb.BestChromosome.Genes)
            {
                Configuration.Instance.Context.DaySchedules.InsertOnSubmit(
                    new Acceron.University.DBAccess.DaySchedule()
                    {
                        Class = gen.Class,
                        DayOfWeek = gen.DayOfWeek,
                        Pair = gen.Pair,
                        Room = gen.Room
                    }
                    );
            }

            Configuration.Instance.Context.SubmitChanges();
            
        }

        Schedule testSch;

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            Acceron.University.DBAccess.GaContext con = new Acceron.University.DBAccess.GaContext();

            var BestSchedule = new Schedule();
            
            foreach (var gen in con.DaySchedules)
            {
                BestSchedule.Genes.Add(new Gen()
                    {
                        Class = gen.Class,
                        DayOfWeek = gen.DayOfWeek,
                        Pair = gen.Pair,
                        Room = gen.Room,
                        Room_id = gen.Room_id,
                        Class_id = gen.Class_id
                    }
                    );
            }
            testSch = BestSchedule;

            algdb_NewBestSchedule(null, new AlgorithmDBEventArgs(BestSchedule, 0));
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            PenaltyManager.Load();

            if (testSch != null)
            {
                testSch.CalculateFitness();
            }
        }


    }
}
